﻿using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Business.Parsers {
    class ZhaoPinResumeParser {
        public Resume Parse(string body) {
            var resume = new Resume();

            var doc = new HtmlDocument();
            doc.LoadHtml(body);

            // <span id="OLK_SRC_BODY_SECTION">中是原始邮件正文
            var resumeNode = doc.DocumentNode.SelectSingleNode("//span[@id='OLK_SRC_BODY_SECTION']");
            resume.HtmlBody = resumeNode.OuterHtml;
            
            resume.Position = ParsePosition(resumeNode);
            resume.Salary = ParseSalary(resumeNode);

            ParseSummary(resumeNode, resume);
            ParseRecentWork(resumeNode, resume);

            return resume;
        }

        /// <summary>
        /// 基本情况
        /// </summary>
        /// <param name="resumeNode"></param>
        /// <param name="resume"></param>
        private void ParseSummary(HtmlNode resumeNode, Resume resume) {
            var nodes = resumeNode.Single("//table[@width='580']").Children("tr").At(1).Children("td");
            
            resume.Name = nodes.At(0).FirstChild("span").InnerHtml;

            var summary = nodes.At(1).InnerHtml;
            resume.Gender = SelectKeyWord(summary, new[] { "男", "女" });
            resume.Marriage = SelectKeyWord(summary, new[] { "已婚", "未婚" });
            resume.BirthYear = ParseBirthYear(summary);
            resume.YearsOfWorking = ParseYearsOfWorkingExperience(summary);
            resume.PhoneNumber = ParsePhoneNumber(summary);
            resume.HuKou = ParseHuKou(summary);
            resume.Education = ParseEducation(summary);
        }

        /// <summary>
        /// 最近工作情况
        /// </summary>
        /// <param name="node"></param>
        private void ParseRecentWork(HtmlNode resumeNode, Resume resume) {
            var lines = resumeNode.Single("//td/span[text()='工作经历']").NearestAncestor("table").NextSibling("table").Children("tr")
                .Split((node) => node.Single("./td[@colspan='2']").IsNotNull())
                .Select(_ => _.FirstOrDefault());

            foreach (var line in lines) {
                var nodes = line.Children("td");

                // 任职时间
                DateTime? from = null;
                DateTime? to = null;
                var timeNode = nodes.At(0);
                var matches = Regex.Matches(timeNode.InnerHtml, @"\d+/\d+", RegexOptions.IgnoreCase | RegexOptions.Singleline);
                if (matches.Count > 0)
                    from = DateTime.ParseExact(matches[0].Value, "yyyy/M", CultureInfo.CurrentCulture);
                if (matches.Count > 1)
                    to = DateTime.ParseExact(matches[1].Value, "yyyy/M", CultureInfo.CurrentCulture);

                // 任职信息
                string company = null;
                string position = null;
                var infoNode = nodes.At(1);
                var m = Regex.Match(infoNode.InnerHtml, @"(.*?)<br>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
                if (m.Success) {
                    var s = m.Groups[1].Value.Split('|');
                    company = s.FirstOrDefault();
                    position = s.LastOrDefault();
                }

                resume.AddWork(from, to, company, position);
            }
        }

        

        private string SelectKeyWord(string summary, IEnumerable<string> keywords) {
            foreach (var word in keywords) {
                if (summary.Contains(word))
                    return word;
            }
            return null;
        }


        private int? ParseBirthYear(string summary) {
            var regex = new Regex(@"(\d{4})\s*年");
            var m = regex.Match(summary);
            if (m.Success)
                return int.Parse(m.Groups[1].Value);
            return null;
        }

        private int? ParseYearsOfWorkingExperience(string summary) {
            var regex = new Regex(@"(\d+)年工作经验");
            var m = regex.Match(summary);
            if (m.Success) {
                return int.Parse(m.Groups[1].Value);
            }
            return null;
        }

        private string ParsePhoneNumber(string summary) {
            var regex = new Regex(@"\d{11}");
            var m = regex.Match(summary);
            if (m.Success)
                return m.Value;
            return null;
        }

        private string ParseHuKou(string summary) {
            var hukou = summary.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries).Where(_ => _.Contains("户口：")).FirstOrDefault();
            if (!string.IsNullOrEmpty(hukou))
                return hukou.Replace("户口：", string.Empty);
            return null;
        }

        private string ParseEducation(string summary) {
            var idx = summary.IndexOf("<br>");
            if (idx >= 0) {
                var firstLine = summary.Substring(0, idx);
                var lastItem = firstLine.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault();
                if (lastItem != null)
                    return lastItem;
            }
            return null;
        }

        private string ParsePosition(HtmlNode resumeNode) {
            var text = resumeNode.SelectSingleNode("div[1]/span[last()]").NextSibling.InnerHtml;
            var idx1 = text.IndexOf("应聘") + 2;
            var idx2 = text.IndexOf("-");
            return text.Substring(idx1, idx2 - idx1);
        }

        private int? ParseSalary(HtmlNode resumeNode) {
            var node = resumeNode.SelectSingleNode("//td[text()[normalize-space()='期望月薪：']]").NextSibling;
            var text = node.InnerHtml;
            var regex = new Regex(@"(\d+)\-\d+元/月");
            var m = regex.Match(text);
            if (m.Success) {
                var number = int.Parse(m.Groups[1].Value);
                return number / 10 * 10;
            }

            if (text != null && text.Contains("面议"))
                return null;
            
            throw new ArgumentException(text);
        }
    }
}
